package com.ssy.lingxi.settle.accounts.serviceimpl;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.ssy.lingxi.after.sale.api.feign.ReturnGoodsControllerFeign;
import com.ssy.lingxi.common.constant.settle.ReceiptInvoiceOrderTypeEnum;
import com.ssy.lingxi.common.constant.settle.SettlementOrderTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.dto.request.InvoiceProveGetVO;
import com.ssy.lingxi.dto.request.MemberReceiptInvoiceBaseVO;
import com.ssy.lingxi.dto.response.InvoiceProveVO;
import com.ssy.lingxi.order.api.model.vo.response.OrderSettleAccountInvoiceFeignDetailVO;
import com.ssy.lingxi.settle.accounts.entity.InvoiceMessage;
import com.ssy.lingxi.settle.accounts.entity.MemberReceiptInvoiceDO;
import com.ssy.lingxi.settle.accounts.entity.MemberReceiptInvoiceProveDO;
import com.ssy.lingxi.settle.accounts.model.bo.InvoiceProveBO;
import com.ssy.lingxi.settle.accounts.model.constant.*;
import com.ssy.lingxi.settle.accounts.model.vo.request.*;
import com.ssy.lingxi.settle.accounts.model.vo.response.MemberReceiptInvoiceDetailVO;
import com.ssy.lingxi.settle.accounts.model.vo.response.MemberReceiptInvoiceVO;
import com.ssy.lingxi.settle.accounts.model.vo.response.MemberReturnReceiptInvoiceDetailVO;
import com.ssy.lingxi.settle.accounts.model.vo.response.PlatformInvoiceDetailVO;
import com.ssy.lingxi.settle.accounts.repository.InvoiceMessageRepository;
import com.ssy.lingxi.settle.accounts.repository.MemberReceiptInvoiceProveRepository;
import com.ssy.lingxi.settle.accounts.repository.MemberReceiptInvoiceRepository;
import com.ssy.lingxi.settle.accounts.service.*;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 开票管理接口实现
 */
@Service
public class MemberReceiptInvoiceServiceImpl implements IMemberReceiptInvoiceService {

    @Resource
    private MemberReceiptInvoiceRepository invoiceRepository;

    @Resource
    private MemberReceiptInvoiceProveRepository invoiceProveRepository;

    @Resource
    private InvoiceMessageRepository invoiceMessageRepository;

    @Resource
    private IPlatformInvoiceService platformInvoiceService;

    @Resource
    private IApplyAmountService applyAmountService;

//    @Resource
//    private IBusinessReconciliationService reconciliationService;

    @Resource
    private IFeignService feignService;

    @Resource
    private ReturnGoodsControllerFeign returnGoodsControllerFeign;

    /**
     * 分页查询票据管理列表
     * @author 伍将
     * @date 2020/10/28
     * @param sysUser:
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.settle.accounts.mode.vo.response.MemberReceiptInvoiceVO>>
     **/
    @Override
    public Wrapper<PageData<MemberReceiptInvoiceVO>> pageReceiptInvoice(UserLoginCacheDTO sysUser, MemberReceiptInvoicePageVO pageVO) {

        // step 1: 组装查询条件
        Specification<MemberReceiptInvoiceDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), sysUser.getMemberId()));
            if (!ReceiptInvoiceStatusEnum.ALL.getCode().equals(pageVO.getInvoiceStatus())) {
                list.add(criteriaBuilder.equal(root.get("invoiceStatus").as(Long.class), pageVO.getInvoiceStatus()));
            }
            if (!ReceiptInvoicePayStatusEnum.ALL.getCode().equals(pageVO.getPayStatus())) {
                list.add(criteriaBuilder.equal(root.get("payStatus").as(Long.class), pageVO.getPayStatus()));
            }
            if (StringUtils.hasLength(pageVO.getOrderStartTime())) {
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("orderTime").as(Long.class), DateUtil.parse(pageVO.getOrderStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getOrderEndTime())) {
                list.add(criteriaBuilder.lessThanOrEqualTo(root.get("orderTime").as(Long.class), DateUtil.parse(pageVO.getOrderEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getPayStartTime())) {
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("payTime").as(Long.class), DateUtil.parse(pageVO.getPayStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getPayEndTime())) {
                list.add(criteriaBuilder.lessThanOrEqualTo(root.get("payTime").as(Long.class), DateUtil.parse(pageVO.getPayEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getOrderNo())) {
                list.add(criteriaBuilder.like(root.get("orderNo").as(String.class), "%" + pageVO.getOrderNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getOrderAbstract())) {
                list.add(criteriaBuilder.like(root.get("orderAbstract").as(String.class), "%" + pageVO.getOrderAbstract().trim() + "%"));
            }
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("orderTime").descending());

        // step 3: 分页查询数据
        Page<MemberReceiptInvoiceDO> result = invoiceRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<MemberReceiptInvoiceVO> resultList = result.getContent().stream().map(r -> {
            MemberReceiptInvoiceVO queryVO = new MemberReceiptInvoiceVO();
            queryVO.setMemberId(r.getMemberId());
            queryVO.setRoleId(r.getRoleId());
            queryVO.setPayMemberId(r.getPayMemberId());
            queryVO.setPayRoleId(r.getPayRoleId());
            queryVO.setId(r.getId());
            queryVO.setOrderNo(r.getOrderNo());
            queryVO.setOrderAbstract(null != r.getOrderAbstract() && !r.getOrderAbstract().equals("null") ? r.getOrderAbstract() : "");
            queryVO.setSettlementOrderType(r.getSettlementOrderType());
            queryVO.setSettlementOrderTypeName(SettlementOrderTypeEnum.getMessage(r.getSettlementOrderType(), ""));
            queryVO.setOrderTime(DateUtil.format(DateUtil.date(r.getOrderTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setOrderTypeName(ReceiptInvoiceOrderTypeEnum.getMessage(r.getOrderType()));
            queryVO.setOrderAmount(r.getOrderAmount());
            queryVO.setBatch(r.getBatch());
            queryVO.setPayNode(Optional.ofNullable(r.getPayNode()).filter(f -> !f.equals("null")).orElse(""));
            queryVO.setPayAmount(r.getPayAmount());
            queryVO.setPayTime((r.getPayTime()==null|| r.getPayTime()== 0) ?"": DateUtil.format(DateUtil.date(r.getPayTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setInvoiceStatus(r.getInvoiceStatus());
            queryVO.setInvoiceStatusName(ReceiptInvoiceStatusEnum.getMessage(r.getInvoiceStatus()));
            queryVO.setPayStatusName(ReceiptInvoicePayStatusEnum.getMessage(r.getPayStatus()));
            queryVO.setDataId(r.getDataId());
            if(r.getIsHasTax()!=null&&r.getIsHasTax()!=-1){//如果不为-1,则正常设置
                queryVO.setIsHasTax(r.getIsHasTax());
                queryVO.setIsHasTaxName(CommonBooleanEnum.getMessage(r.getIsHasTax()));
            }
            queryVO.setTaxRate(r.getTaxRate());
            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 开票
     * @param sysUser 登录用户
     * @param addVO 接口参数
     * @return 操作结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> invoice(UserLoginCacheDTO sysUser, AddReceiptInvoiceVO addVO) {
        // step1: 校验
        MemberReceiptInvoiceDO entity = invoiceRepository.findById(addVO.getReceiptInvoiceId()).orElse(null);
        if (entity == null) {
            throw new BusinessException(ResponseCode.SA_MEMBER_RECEIPT_INVOICE_NOT_EXIST);
        }

        if (!ReceiptInvoiceStatusEnum.NO.getCode().equals(entity.getInvoiceStatus())) {
            throw new BusinessException(ResponseCode.SA_MEMBER_RECEIPT_INVOICE_NO_UPDATE);
        }
        // step2: 更新主表
        entity.setInvoiceStatus(ReceiptInvoiceStatusEnum.YES.getCode());
        invoiceRepository.saveAndFlush(entity);
        // step3: 更新子表
        MemberReceiptInvoiceProveDO proveDO = new MemberReceiptInvoiceProveDO();
        proveDO.setReceiptInvoiceId(addVO.getReceiptInvoiceId());
        proveDO.setKind(addVO.getKind());
        proveDO.setType(addVO.getType());
        proveDO.setInvoiceTitle(addVO.getInvoiceTitle());
        proveDO.setTaxNo(addVO.getTaxNo());
        proveDO.setBankOfDeposit(addVO.getBankOfDeposit());
        proveDO.setAccount(addVO.getAccount());
        proveDO.setAddress(addVO.getAddress());
        proveDO.setTel(addVO.getTel());
        proveDO.setInvoiceProveList(addVO.getProveList());
        invoiceProveRepository.saveAndFlush(proveDO);
        // step4: 根据单据类型 做不同业务操作
        if (entity.getSettlementOrderType().equals(SettlementOrderTypeEnum.RECONCILIATION.getCode())) {
            Long reconciliationId = entity.getDataId();
            Wrapper<Void> result = applyAmountService.addInvoiceRecord(reconciliationId, entity.getId(), proveDO.getId(), addVO.getProveList());
            if (result.getCode() != ResponseCode.SUCCESS.getCode()) {
                // 设置回滚事务
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return result;
            }
        }
        // 新增操作通知
        feignService.addReceiptInvoiceOperateNotice(entity.getMemberId(), entity.getRoleId(), entity.getInvoiceStatus());

        return Wrapper.success();
    }

    /**
     * 售后退货开票
     * @author 伍将
     * @date 2020/10/28
     * @param sysUser: 当前登录用户
     * @param addVO: 开票信息
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Transactional
    @Override
    public Wrapper<Void> invoiceByReturn(UserLoginCacheDTO sysUser, AddReceiptInvoiceListVO addVO) {

        MemberReceiptInvoiceDO entity = invoiceRepository.findById(addVO.getReceiptInvoiceId()).orElse(null);
        if (entity == null) {
            throw new BusinessException(ResponseCode.SA_MEMBER_RECEIPT_INVOICE_NOT_EXIST);
        }

        if (!ReceiptInvoiceStatusEnum.NO.getCode().equals(entity.getInvoiceStatus())) {
            throw new BusinessException(ResponseCode.SA_MEMBER_RECEIPT_INVOICE_NO_UPDATE);
        }

        entity.setInvoiceStatus(ReceiptInvoiceStatusEnum.YES.getCode());
        invoiceRepository.saveAndFlush(entity);

        List<MemberReceiptInvoiceProveDO> proveList = addVO.getAddList().stream().map(r -> {
            MemberReceiptInvoiceProveDO proveDO = new MemberReceiptInvoiceProveDO();
            proveDO.setReceiptInvoiceId(addVO.getReceiptInvoiceId());
            proveDO.setKind(r.getKind());
            proveDO.setType(r.getType());
            proveDO.setInvoiceTitle(r.getInvoiceTitle());
            proveDO.setTaxNo(r.getTaxNo());
            proveDO.setBankOfDeposit(r.getBankOfDeposit());
            proveDO.setAccount(r.getAccount());
            proveDO.setAddress(r.getAddress());
            proveDO.setTel(r.getTel());
            proveDO.setOriginalInvoiceProveList(r.getOriginalInvoiceProveList());
            proveDO.setInvoiceProveList(r.getProveList());
            return proveDO;
        }).collect(Collectors.toList());
        invoiceProveRepository.saveAll(proveList);

        // 新增操作通知
        feignService.addReceiptInvoiceOperateNotice(entity.getMemberId(), entity.getRoleId(), entity.getInvoiceStatus());

        return Wrapper.success();
    }


    /**
     * 获取发票详情
     * @author 伍将
     * @date 2020/10/28
     * @param sysUser: 当前登录用户
     * @param receiptInvoiceId: 开票数据id
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.settle.accounts.mode.vo.response.MemberReceiptInvoiceDetailVO>
     **/
    @Override
    public Wrapper<MemberReceiptInvoiceDetailVO> getInvoiceProveDetail(UserLoginCacheDTO sysUser, Long receiptInvoiceId) {

        MemberReceiptInvoiceDO receiptInvoiceDO = invoiceRepository.findById(receiptInvoiceId).orElse(null);
        if (receiptInvoiceDO == null) {
            throw new BusinessException(ResponseCode.SA_MEMBER_RECEIPT_INVOICE_NOT_EXIST);
        }

        MemberReceiptInvoiceDetailVO result = new MemberReceiptInvoiceDetailVO();
        MemberReceiptInvoiceProveDO entity = invoiceProveRepository.findByReceiptInvoiceId(receiptInvoiceId);
        // 未开票则查询相关票据信息
        if (entity == null) {
            // 如果单据类型为物流单、生产通知单、请款单、物料对账单，则发票信息来源于结算能力--发票信息管理的默认发票信息
            if (SettlementOrderTypeEnum.LOGISTICS.getCode().equals(receiptInvoiceDO.getSettlementOrderType())
                    || SettlementOrderTypeEnum.PRODUCTION_NOTICE.getCode().equals(receiptInvoiceDO.getSettlementOrderType())
                    || SettlementOrderTypeEnum.RECONCILIATION.getCode().equals(receiptInvoiceDO.getSettlementOrderType())
                    || SettlementOrderTypeEnum.APPLY_AMOUNT.getCode().equals(receiptInvoiceDO.getSettlementOrderType())) {
                InvoiceMessage invoiceMessage = invoiceMessageRepository.findByIsDefaultAndMemberIdAndCreateRoleId(CommonBooleanEnum.YES.getCode(), receiptInvoiceDO.getPayMemberId(), receiptInvoiceDO.getPayRoleId());
                if (Objects.isNull(invoiceMessage)) {
                    return Wrapper.fail(ResponseCode.SA_PAY_BILLING_VOUCHER_NOT_EXIST);
                }
                result.setKindName(InvoiceKindEnum.getMessage(invoiceMessage.getKind()));
                result.setTypeName(InvoiceTypeEnum.getMessage(invoiceMessage.getType()));
                result.setInvoiceTitle(invoiceMessage.getInvoiceTitle());
                result.setTaxNo(invoiceMessage.getTaxNo());
                result.setBankOfDeposit(invoiceMessage.getBankOfDeposit());
                result.setAccount(invoiceMessage.getAccount());
                result.setAddress(invoiceMessage.getAddress());
                result.setTel(invoiceMessage.getTel());
                result.setKind(invoiceMessage.getKind());
                result.setType(invoiceMessage.getType());
            }
            // 如果单据类型为订单，则发票信息来源于订单发票信息栏
            else if (SettlementOrderTypeEnum.ORDER.getCode().equals(receiptInvoiceDO.getSettlementOrderType())) {
                Wrapper<OrderSettleAccountInvoiceFeignDetailVO> wrapper = feignService.findSettleAccountInvoiceDetail(receiptInvoiceDO.getOrderNo());
                if (null != wrapper && ResponseCode.SUCCESS.getCode() == wrapper.getCode() && null != wrapper.getData()) {
                    result.setKindName(InvoiceKindEnum.getMessage(wrapper.getData().getInvoiceKind()));
                    result.setTypeName(InvoiceTypeEnum.getMessage(wrapper.getData().getInvoiceType()));
                    result.setInvoiceTitle(wrapper.getData().getTitle());
                    result.setTaxNo(wrapper.getData().getTaxNo());
                    result.setBankOfDeposit(wrapper.getData().getBank());
                    result.setAccount(wrapper.getData().getAccount());
                    result.setAddress(wrapper.getData().getAddress());
                    result.setTel(wrapper.getData().getPhone());
                    result.setKind(wrapper.getData().getInvoiceKind());
                    result.setType(wrapper.getData().getInvoiceType());
                }
            }
            // 如果单据类型为积分订单，则发票信息来源于平台后台--结算管理--平台发票信息管理的默认发票信息
            else if (SettlementOrderTypeEnum.SCORE_ORDER.getCode().equals(receiptInvoiceDO.getSettlementOrderType())) {
                Wrapper<PlatformInvoiceDetailVO> wrapper = platformInvoiceService.getDefaultDetail();
                if (null != wrapper && ResponseCode.SUCCESS.getCode() == wrapper.getCode() && null != wrapper.getData()) {
                    result.setKindName(InvoiceKindEnum.getMessage(wrapper.getData().getKind()));
                    result.setTypeName(InvoiceTypeEnum.getMessage(wrapper.getData().getType()));
                    result.setInvoiceTitle(wrapper.getData().getInvoiceTitle());
                    result.setTaxNo(wrapper.getData().getTaxNo());
                    result.setBankOfDeposit(wrapper.getData().getBankOfDeposit());
                    result.setAccount(wrapper.getData().getAccount());
                    result.setAddress(wrapper.getData().getAddress());
                    result.setTel(wrapper.getData().getTel());
                    result.setKind(wrapper.getData().getKind());
                    result.setType(wrapper.getData().getType());
                }
            }
        }
        // 已开票，直接返回
        else {
            result.setKindName(InvoiceKindEnum.getMessage(entity.getKind()));
            result.setTypeName(InvoiceTypeEnum.getMessage(entity.getType()));
            result.setInvoiceTitle(entity.getInvoiceTitle());
            result.setTaxNo(entity.getTaxNo());
            result.setBankOfDeposit(entity.getBankOfDeposit());
            result.setAccount(entity.getAccount());
            result.setAddress(entity.getAddress());
            result.setTel(entity.getTel());
            result.setProveList(entity.getInvoiceProveList());
            result.setKind(entity.getKind());
            result.setType(entity.getType());
        }

        return Wrapper.success(result);
    }

    /**
     * 获取退货发票详情
     * @param sysUser：当前登录用户
     * @param receiptInvoiceId：开票数据id
     * @return 发票列表
     */
    @Override
    public Wrapper<List<MemberReturnReceiptInvoiceDetailVO>> getReturnInvoiceProveDetail(UserLoginCacheDTO sysUser, Long receiptInvoiceId) {
        MemberReceiptInvoiceDO receiptInvoiceDO = invoiceRepository.findById(receiptInvoiceId).orElse(null);
        if (receiptInvoiceDO == null) {
            throw new BusinessException(ResponseCode.SA_MEMBER_RECEIPT_INVOICE_NOT_EXIST);
        }

        List<MemberReturnReceiptInvoiceDetailVO> resultLis;
        List<MemberReceiptInvoiceProveDO> proveList = invoiceProveRepository.findAllByReceiptInvoiceId(receiptInvoiceId);
        if (proveList.size() > 0) {
            resultLis = proveList.stream().map(r -> {
                MemberReturnReceiptInvoiceDetailVO entity = new MemberReturnReceiptInvoiceDetailVO();
                entity.setOrderNo(r.getOrderNo());
                entity.setKind(r.getKind());
                entity.setKindName(InvoiceKindEnum.getMessage(r.getKind()));
                entity.setType(r.getType());
                entity.setTypeName(InvoiceTypeEnum.getMessage(r.getType()));
                entity.setInvoiceTitle(r.getInvoiceTitle());
                entity.setTaxNo(r.getTaxNo());
                entity.setBankOfDeposit(r.getBankOfDeposit());
                entity.setAccount(r.getAccount());
                entity.setAddress(r.getAddress());
                entity.setTel(r.getTel());
                entity.setProveList(r.getInvoiceProveList());
                entity.setOriginalProveList(r.getOriginalInvoiceProveList());
                return entity;
            }).collect(Collectors.toList());
        } else {
            resultLis = new ArrayList<>();
            Wrapper<List<String>> listWrapper = returnGoodsControllerFeign.getOrderList(receiptInvoiceDO.getOrderNo());
            if (null != listWrapper && listWrapper.getCode() == ResponseCode.SUCCESS.getCode() && null != listWrapper.getData()) {
                // 循环组装发票
                for (String orderNo : listWrapper.getData()) {
                    MemberReturnReceiptInvoiceDetailVO entity = getOrderProveDetail(orderNo);
                    if (StringUtils.hasLength(entity.getKindName())) {
                        resultLis.add(entity);
                    }
                }
            }
        }

        return Wrapper.success(resultLis);
    }

    /**
     * 查询订单退货发票详情
     * @author 伍将
     * @date 2021/1/27
     * @param orderNo: 订单号
     * @return 退货发票详情
     **/
    private MemberReturnReceiptInvoiceDetailVO getOrderProveDetail(String orderNo) {

        MemberReturnReceiptInvoiceDetailVO result = new MemberReturnReceiptInvoiceDetailVO();
        result.setOrderNo(orderNo);
        List<MemberReceiptInvoiceDO> invoiceList = invoiceRepository.findAllByOrderNoAndSettlementOrderType(orderNo, SettlementOrderTypeEnum.ORDER.getCode());
        if (invoiceList.size() > 0) {
            for (MemberReceiptInvoiceDO invoiceDO : invoiceList) {
                MemberReceiptInvoiceProveDO entity = invoiceProveRepository.findByReceiptInvoiceId(invoiceDO.getId());
                // 未开票则查询相关票据信息
                if (entity == null) {
                    Wrapper<OrderSettleAccountInvoiceFeignDetailVO> wrapper = feignService.findSettleAccountInvoiceDetail(invoiceDO.getOrderNo());
                    if (null != wrapper && ResponseCode.SUCCESS.getCode() == wrapper.getCode() && null != wrapper.getData()) {
                        result.setKindName(InvoiceKindEnum.getMessage(wrapper.getData().getInvoiceKind()));
                        result.setTypeName(InvoiceTypeEnum.getMessage(wrapper.getData().getInvoiceType()));
                        result.setInvoiceTitle(wrapper.getData().getTitle());
                        result.setTaxNo(wrapper.getData().getTaxNo());
                        result.setBankOfDeposit(wrapper.getData().getBank());
                        result.setAccount(wrapper.getData().getAccount());
                        result.setAddress(wrapper.getData().getAddress());
                        result.setTel(wrapper.getData().getPhone());
                    }
                }
                // 已开票，直接返回
                else {
                    result.setKindName(InvoiceKindEnum.getMessage(entity.getKind()));
                    result.setTypeName(InvoiceTypeEnum.getMessage(entity.getType()));
                    result.setInvoiceTitle(entity.getInvoiceTitle());
                    result.setTaxNo(entity.getTaxNo());
                    result.setBankOfDeposit(entity.getBankOfDeposit());
                    result.setAccount(entity.getAccount());
                    result.setAddress(entity.getAddress());
                    result.setTel(entity.getTel());
                    if (null == result.getOriginalProveList()) {
                        result.setOriginalProveList(entity.getInvoiceProveList());
                    } else {
                        result.getOriginalProveList().addAll(entity.getInvoiceProveList());
                    }
                }
            }
        }

        return result;
    }

    /**
     * 获取发票凭证
     * @author 伍将
     * @date 2021/3/10
     * @param sysUser: 当前登录用户
     * @param getVO: 请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<List<InvoiceProveVO>> getInvoiceProve(UserLoginCacheDTO sysUser, InvoiceProveGetVO getVO) {
        List<InvoiceProveVO> resultList = new ArrayList<>();

        // 查询会员发票主表
        List<MemberReceiptInvoiceDO> InvoiceList = invoiceRepository.findAllByOrderNoAndSettlementOrderType(getVO.getOrderNo(), getVO.getSettlementOrderType());
        if (InvoiceList.size() > 0) {
            // 循环查询发票凭证
            for (MemberReceiptInvoiceDO item : InvoiceList) {
                MemberReceiptInvoiceProveDO prove = invoiceProveRepository.findByReceiptInvoiceId(item.getId());
                if (null != prove && null != prove.getInvoiceProveList() && prove.getInvoiceProveList().size() > 0) {
                    for (InvoiceProveBO proveBO : prove.getInvoiceProveList()) {
                        InvoiceProveVO proveVO = new InvoiceProveVO();
                        proveVO.setNumber(proveBO.getNumber());
                        proveVO.setInvoiceDate(proveBO.getInvoiceDate());
                        proveVO.setInvoiceAmount(proveBO.getInvoiceAmount());
                        resultList.add(proveVO);
                    }
                }
            }
        }

        return Wrapper.success(resultList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Wrapper<Void> save(MemberReceiptInvoiceBaseVO saveVOS) {
        // step1: 新增开票记录
        MemberReceiptInvoiceDO entity = new MemberReceiptInvoiceDO();
        entity.setIsHasTax(saveVOS.getIsHasTax());
        entity.setTaxRate(saveVOS.getTaxRate());
        entity.setPayMemberId(saveVOS.getPayMemberId());
        entity.setPayRoleId(saveVOS.getPayRoleId());
        entity.setDataId(saveVOS.getDataId());
        entity.setMemberId(saveVOS.getMemberId());
        entity.setRoleId(saveVOS.getRoleId());
        entity.setSettlementOrderType(saveVOS.getSettlementOrderType());
        entity.setOrderType(saveVOS.getOrderType());
        entity.setOrderTime(saveVOS.getOrderTime());
        entity.setOrderAmount(saveVOS.getOrderAmount());
        entity.setBatch(saveVOS.getBatch());
        entity.setPayNode(saveVOS.getPayNode());
        entity.setPayAmount(saveVOS.getPayAmount());
        entity.setPayTime(saveVOS.getPayTime());
        entity.setInvoiceStatus(saveVOS.getInvoiceStatus());
        entity.setPayStatus(saveVOS.getPayStatus());
        entity.setOrderNo(saveVOS.getOrderNo());
        entity.setOrderAbstract(saveVOS.getOrderAbstract());
        invoiceRepository.saveAndFlush(entity);
        // step2: 系统通知

        return Wrapper.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Wrapper<Void> pay(List<Long> invoiceIdList, Integer type, Long dataId) {
        if (CollectionUtils.isEmpty(invoiceIdList)) {
            if (SettlementOrderTypeEnum.RECONCILIATION.getCode().equals(type)) {
                Specification<MemberReceiptInvoiceDO> spec = (root, query, cb) -> query.where(cb.equal(root.get("dataId").as(Long.class), dataId), cb.equal(root.get("settlementOrderType").as(Integer.class), type)).getRestriction();
                MemberReceiptInvoiceDO entity = invoiceRepository.findAll(spec).stream().findFirst().orElse(null);
                if (Objects.isNull(entity)) {
                    return Wrapper.success();
                }
                entity.setPayStatus(ReceiptInvoicePayStatusEnum.YES.getCode());
                entity.setPayTime(System.currentTimeMillis());
                invoiceRepository.saveAndFlush(entity);
            }
            return Wrapper.success();
        }
        // step1: 查询开票记录
        Specification<MemberReceiptInvoiceDO> specification = (root, query, cb) -> {
            CriteriaBuilder.In<Long> in = cb.in(root.get("id").as(Long.class));
            invoiceIdList.forEach(in::value);
            return in;
        };
        List<MemberReceiptInvoiceDO> entities = invoiceRepository.findAll(specification);
        Long payTime = System.currentTimeMillis();
        // step2: 更新开票支付完成
        entities.forEach(map -> {
            map.setPayStatus(ReceiptInvoicePayStatusEnum.YES.getCode());
            map.setPayTime(payTime);
            invoiceRepository.saveAndFlush(map);
        });
        return Wrapper.success();
    }

    @Override
    public Wrapper<AddBatchReceiptInvoiceVO> generateBatchInvoiceProve(UserLoginCacheDTO sysUser, AddBatchReceiptInvoiceIdsVO receiptInvoiceIds) {
        // step1: 查询对应所有的开票列表
        List<Long> ids = receiptInvoiceIds.getReceiptInvoiceIds();
        List<MemberReceiptInvoiceDO> entities = invoiceRepository.findAllById(ids);
        if (ids.size() > entities.size()) {
            return Wrapper.fail(ResponseCode.SA_MEMBER_RECEIPT_INVOICE_NOT_EXIST);
        }
        // 校验是否都是请款单
        long count = entities.stream().map(f -> f.getPayMemberId() + f.getPayRoleId() + BigDecimal.valueOf(f.getTaxRate()).setScale(2, RoundingMode.HALF_UP).toString()).distinct().count();
        if (count > 1) {
            return Wrapper.fail(ResponseCode.SA_MEMBER_RECEIPT_INVOICE_UNABLE_TO_MERGE);
        }
        MemberReceiptInvoiceDO entity = entities.get(0);
        // step2: 查询对应的会员收据发票凭证
        InvoiceMessage invoiceMessage = invoiceMessageRepository.findByIsDefaultAndMemberIdAndCreateRoleId(CommonBooleanEnum.YES.getCode(), entity.getPayMemberId(), entity.getPayRoleId());
        if (Objects.isNull(invoiceMessage)) {
            return Wrapper.fail(ResponseCode.SA_BILLING_VOUCHER_NOT_EXIST);
        }
        // step4: 组装数据
        AddBatchReceiptInvoiceVO data = new AddBatchReceiptInvoiceVO();
        data.setReceiptInvoiceIds(ids);
        data.setKind(invoiceMessage.getKind());
        data.setKindName(InvoiceKindEnum.getMessage(invoiceMessage.getKind()));
        data.setType(invoiceMessage.getType());
        data.setTypeName(InvoiceTypeEnum.getMessage(invoiceMessage.getType()));
        data.setInvoiceTitle(invoiceMessage.getInvoiceTitle());
        data.setTaxNo(invoiceMessage.getTaxNo());
        data.setBankOfDeposit(invoiceMessage.getBankOfDeposit());
        data.setAccount(invoiceMessage.getAccount());
        data.setAddress(invoiceMessage.getAddress());
        data.setTel(invoiceMessage.getTel());
        data.setProveList(Lists.newArrayList());
        return Wrapper.success(data);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Wrapper<Void> batchInvoiceProve(UserLoginCacheDTO sysUser, AddBatchReceiptInvoiceVO batchAddVO) {
        // step1: 组装原生当个开票操作
        List<AddReceiptInvoiceVO> addVOList = batchAddVO.getReceiptInvoiceIds().stream().map(map -> {
            AddReceiptInvoiceVO addVO = new AddBatchReceiptInvoiceVO();
            addVO.setReceiptInvoiceId(map);
            addVO.setKind(batchAddVO.getKind());
            addVO.setType(batchAddVO.getType());
            addVO.setInvoiceTitle(batchAddVO.getInvoiceTitle());
            addVO.setTaxNo(batchAddVO.getTaxNo());
            addVO.setBankOfDeposit(batchAddVO.getBankOfDeposit());
            addVO.setAccount(batchAddVO.getAccount());
            addVO.setAddress(batchAddVO.getAddress());
            addVO.setTel(batchAddVO.getTel());
            addVO.setProveList(batchAddVO.getProveList());
            return addVO;
        }).collect(Collectors.toList());
        // step2: 遍历调用原有单个开票
        addVOList.forEach(value -> invoice(sysUser, value));
        return Wrapper.success();
    }
}
